package com.jarman.kit;

import com.google.common.base.CaseFormat;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jarman on 2017/5/4.
 */
public class CodeGenerator {

    private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
    private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/cub";
    private static final String DATABASE_USER = "jarman";
    private static final String DATABASE_PASSWORD = "123456";
    private static final String DATABASE_NAME = "kit";

    //驱动包路径
    private static final String DRIVER_PATH = "src/main/resources/templates/mysql-connector-java-5.1.37.jar";
    private static Connection con = null;
    /**
     * 模板文件路径
     */
    private static final String TEMPLATE_FILE = "src/main/resources/templates/generatorConfigTemplate.xml";
    /**
     * 要生成的文件
     */
    private static final String TARGET_FILE = "src/main/resources/generatorConfig.xml";
    /**
     * 项目路径
     */
    private static final String PROJECT_ROOT = System.getProperty("user.dir");
    /**
     * 生成的实体类包名（可修改）
     */
    private static final String ENTITY_PACKAGE = "com.jarman.kit.entity";
    /**
     * 映射文件包名（可修改）
     */
    private static final String XML_MAPPER_PACKAGE = "com.jarman.kit.mapper";
    /**
     * mapper xml文件目录（可修改）
     */
    private static final String MAPPER_XML_PATH = "src/main/resources/mapper/";

    /**
     * 生成实体类要忽略的表前缀（可修改）
     */
    private static final String IGNORE_PREFIX_LIST = "app_,sys_";

    private Connection getConnection() {
        try {
            Class.forName(DRIVER_CLASS);
            con = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
            return con;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 获取表名
     *
     * @param con
     * @return
     * @throws SQLException
     */
    private List<String> getTableNames(Connection con) throws SQLException {
        List<String> tableNameList = new ArrayList<>();
        try {
            DatabaseMetaData meta = con.getMetaData();
            ResultSet rs = meta.getTables(null, null, null, new String[]{"TABLE"});
            while (rs.next()) {
                String tableName = rs.getString(3);
                System.out.println("表名：" + tableName);
                System.out.println("------------------------------");
                tableNameList.add(tableName);
            }
        } catch (Exception e) {
            try {
                con.close();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.close();
            }
        }
        return tableNameList;
    }

    /**
     * 表名对应java实体类
     *
     * @return map key 表名，value 实体类
     * @throws SQLException
     */
    public Map<String, String> getTableNamesForMap() throws SQLException {
        CodeGenerator generator = new CodeGenerator();
        Connection con = generator.getConnection();
        List<String> tableNameList = generator.getTableNames(con);
        if (tableNameList != null && tableNameList.size() > 0) {
            Map<String, String> resultMap = new HashMap<>();
            for (String tableName : tableNameList) {
                String entityName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, cutPreFixOfTableName(tableName));
                resultMap.put(tableName, entityName);
            }
            return resultMap;
        }
        return null;
    }

    private String cutPreFixOfTableName(String tableName) {
        if (IGNORE_PREFIX_LIST == null || "".equals(IGNORE_PREFIX_LIST)) {
            return tableName;
        }
        String[] ignoreArr = IGNORE_PREFIX_LIST.split(",");
        for (String preFix : ignoreArr) {
            if (tableName.indexOf(preFix) == 0) {
                return tableName.substring(preFix.length());
            }
        }
        return tableName;
    }

    /**
     * 更新mbg配置模板
     */
    private void updateMybatisTemplate() throws SQLException, IOException {
        CodeGenerator generator = new CodeGenerator();
        Map<String, String> resultMap = generator.getTableNamesForMap();
        if (resultMap == null) {
            System.out.println("=========库里没有表==========");
            return;
        }
        VelocityContext context = new VelocityContext();
        //填充模板内容
        context.put("tableMap", resultMap);
        context.put("database", DATABASE_NAME);
        context.put("conUrl", DATABASE_URL);
        context.put("pwd", DATABASE_PASSWORD);
        context.put("driver", DRIVER_PATH);
        context.put("entity", ENTITY_PACKAGE);
        context.put("xmlMapper", XML_MAPPER_PACKAGE);
        File file = new File(TARGET_FILE);
        Template template = Velocity.getTemplate(TEMPLATE_FILE, "UTF-8");
        FileWriter writer = null;
        try {
            writer = new FileWriter(file);
            template.merge(context, writer);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    private void deleteMapperXML() {
        File fileDir = new File(MAPPER_XML_PATH);
        if (fileDir.isDirectory()) {
            String[] files = fileDir.list();
            for (String file : files) {
                new File(MAPPER_XML_PATH + file).deleteOnExit();
            }
        }
    }

    private void genCode() {
        System.out.println("=======genCode start========");
        Runtime runtime = Runtime.getRuntime();
        String cdCmd = "cd " + PROJECT_ROOT;
        String mvnCmd = "mvn -Dmybatis.generator.overwrite=true mybatis-generator:generate";
        try {
            runtime.exec(cdCmd);
            runtime.exec(mvnCmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("=======genCode end========");
    }

    public static void main(String[] args) throws IOException, SQLException {
        CodeGenerator generator = new CodeGenerator();
        //更新mbg配置模板
        generator.updateMybatisTemplate();
        //删除src/main/resources/mapper目录的xml文件
        generator.deleteMapperXML();
        //执行mbg maven命令，重新生成代码
        generator.genCode();
    }
}
